//ParallaxOcclusionMappingFX.h
//Created 17/05/14
//Created By Daniel Bowler
//
//Represents the effect used to render geometry with Parallax Occlusion Mapping (POM).
//
//This is an advanced effect used to model mesh details without modifying the underlying
//mesh complexity (like Displacement mapping). It's more costly than normal mapping but
//produces excellent looking results. 
//
//The effect uses a per pixel raytrace to sample a height field in tangent space to calc
//the parallax offset of the tex coordinate. 

#pragma once

#include "AbstractFX.h"

class ParallaxOcclusionMappingFX : public AbstractFX
{
	//Ensure that the ShaderManager can access private functions - the constructor/
	//destructor. Thus, the ShaderManager will be the only class allowed to 
	//create/destroy Effects.
	friend ShaderManager;
public:
	//Per vertex structure.
	struct PerVertex
	{
		XMFLOAT3 PosL;
		XMFLOAT3 NormalL;
		XMFLOAT2 Tex;
		XMFLOAT3 TangentL;
	};

	//Sets cbuffer data
	void SetCBufferPerObject(CXMMATRIX& world,
		CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj, CXMMATRIX& texTrans, Material& mat, 
		CXMMATRIX& worldView);

	//Set render target dimension data
	void SetRTDimensions(unsigned width, unsigned height);

	//Set Texture Data
	void SetShaderResources(ID3D11ShaderResourceView* diffuseMap,
		ID3D11ShaderResourceView* normalHeightMap,
		ID3D11ShaderResourceView* sepHM = 0, 
		ID3D11ShaderResourceView* specMap = 0,
		ID3D11ShaderResourceView* glossMap = 0);

	//Set lighting data.
	void SetLightingData(XMFLOAT3& eye, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* lightListIndexBuffer, 
		ID3D11ShaderResourceView* lightListStartEndBuffer);
	
	//Sets hemispherical ambient colour data
	void SetHemisphericalData(XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange);

	//Set SSAO Map and transform data
	void SetSSAOData(ID3D11ShaderResourceView* ssaoTex, CXMMATRIX &transform);

	//Sets the environment map - Note Material::Reflection determins how
	//much of the enviromnet is reflected on the model. Very shiny models
	//should have more reflectivity and mat models less. Also, flat models
	//should NOT have any reflectivity because the effect looks shit. 
	void SetEnvironmentMap(ID3D11ShaderResourceView* envCubeMap);

	//Set Light List Buffer (Global lights buffer - Shader Manager can call this)
	void SetLightListBuffer(ID3D11ShaderResourceView* lightListBuffer);
	
	//Sets shadow map
	void SetShadowMap(ID3D11ShaderResourceView* shadowMap);
	void SetShadowMapMatricies(CXMMATRIX &view, CXMMATRIX &proj, CXMMATRIX &toTex);

	//Set POM Data
	void SetPOMData(float heightScale, int minSamples, int maxSamples);

private:
	ParallaxOcclusionMappingFX(ID3D11Device* device);
	~ParallaxOcclusionMappingFX();
	//Disable copy constrcutor and assignment operator
	ParallaxOcclusionMappingFX(ParallaxOcclusionMappingFX& copy);
	ParallaxOcclusionMappingFX& operator=(ParallaxOcclusionMappingFX& other);

	//Override the init methods.
	void InitInputLayout(ID3D11Device* device);
	void InitShaderVariablePointers();

private:
	//Variables.
	//
	//Cbuffer Data:
	ID3DX11EffectMatrixVariable* worldVar;
	ID3DX11EffectMatrixVariable* worldInvTransVar;
	ID3DX11EffectMatrixVariable* worldViewProjVar;
	ID3DX11EffectMatrixVariable* texTransformVar;

	//Render dimensions
	ID3DX11EffectScalarVariable* rtWidthVar;
	ID3DX11EffectScalarVariable* rtHeightVar;

	//Texture Data:
	ID3DX11EffectShaderResourceVariable* diffuseMapVar;
	ID3DX11EffectShaderResourceVariable* normalHeightMapVar;  //Heightfield in .a
	ID3DX11EffectShaderResourceVariable* sepHmVar; //Height in .r componet of this tex rather than .a of NM. 

	//Controls (per pixel) specular lighting. 
	ID3DX11EffectShaderResourceVariable* specMapVar;
	ID3DX11EffectShaderResourceVariable* glossMapVar;

	//Lighting data
	ID3DX11EffectVectorVariable* eyePosVar;
	ID3DX11EffectVariable* materialVar;
	//Direc Lights
	ID3DX11EffectVariable* direcLightVar;
	ID3DX11EffectScalarVariable* direcLightCountVar;
	//Point/Spot lights - Tile Forward System
	ID3DX11EffectShaderResourceVariable* llbVar;
	ID3DX11EffectShaderResourceVariable* llibVar;
	ID3DX11EffectShaderResourceVariable* llsebVar;
	
	//Hemispheric Ambient lighting colours
	ID3DX11EffectVectorVariable* hemiColDownVar;
	ID3DX11EffectVectorVariable* hemiColRangeVar;

	//SSAO
	ID3DX11EffectMatrixVariable* worldViewVar;
	ID3DX11EffectShaderResourceVariable* ssaoMapVar;
	ID3DX11EffectMatrixVariable* ssaoWorldViewProjTexVar;

	//Environment map
	ID3DX11EffectShaderResourceVariable* envMapVar;
	
	//Shadow Map
	ID3DX11EffectShaderResourceVariable* shadowMapVar;
	ID3DX11EffectMatrixVariable* shadowMapViewVar;
	ID3DX11EffectMatrixVariable* shadowMapProjVar;
	ID3DX11EffectMatrixVariable* shadowMapToTexVar;

	//POM
	ID3DX11EffectScalarVariable* heightScaleVar;
	ID3DX11EffectScalarVariable* minSampleVar;
	ID3DX11EffectScalarVariable* maxSampleVar;
};